/*
 * Copyright 2010 Florian Sauter
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * Closure Compiler:
 * http://closure-compiler.appspot.com/home
 * 
 * // ==ClosureCompiler==
 * // @compilation_level SIMPLE_OPTIMIZATIONS
 * // @output_file_name application.js
 * // ==/ClosureCompiler==
 * 
 */
Ext.ns('Messenger', 'Messenger.ui', 'Messenger.data');

var rootPanel;
var messageStore;

/**
 * The basic message model for client-server REST communication.	
 */
Ext.regModel('Message', {
	fields: ['id', 'message', 'author', 'timestamp']
});

Messenger.ui.RootPanel = Ext.extend(Ext.Panel, {
    fullscreen: true,
    cardSwitchAnimation: {type: 'fade', duration: 500},
    layout: {
    	type: 'card'
    }
});

Messenger.ui.MessageList = Ext.extend(Ext.List, {
	id: 'messageList',
	flex: 1,
	width: Ext.is.Phone ? undefined : 300,
    height: 400,
    xtype: 'list',
    scroll: 'vertical',
    itemTpl: '<tpl><div class="messageItem"><div class="author">{author} ({[new Date(values.timestamp).toGMTString()]}):&nbsp;</div><div class="message">{message}</div></div></tpl>',
    grouped: true
});

Messenger.ui.NorthToolbar = Ext.extend(Ext.Toolbar, {
	dock : 'top',
    title: 'Messenger',
    defaults: {
        iconMask: true
    },
    teamCallbackHandler: function() {},
    logoutCallbackHandler: function() {},
    constructor: function(config) {
    	this.teamCallbackHandler = config.teamCallbackHandler;
    	this.logoutCallbackHandler = config.logoutCallbackHandler;
    	Messenger.ui.NorthToolbar.superclass.constructor.apply(this);
    },
    initComponent:function() {
    	this.teamButton = {
    		iconCls: 'settings',
    		title: 'Settings',
        	handler: this.teamCallbackHandler
    	}
    	this.logoutButton = {
    		text: 'Logout',
        	handler: this.logoutCallbackHandler
    	}
    	this.items = this.items || [];
    	this.items.unshift(this.logoutButton);
    	this.items.unshift({xtype: 'spacer'});
    	this.items.unshift(this.teamButton);
    	Messenger.ui.NorthToolbar.superclass.initComponent.call(this);
    } 
});

Messenger.ui.SouthToolbar = Ext.extend(Ext.Toolbar, {
	composeCallbackHandler: function(){},
	reloadCallbackHandler: function(){},
	dock : 'bottom',
    layout: {
        pack: 'center'
    },
    defaults: {
        iconMask: true,
        ui: 'plain'
    },
    constructor: function(config) {
    	this.composeCallbackHandler = config.composeCallbackHandler;
    	this.reloadCallbackHandler = config.reloadCallbackHandler;
    	Messenger.ui.SouthToolbar.superclass.constructor.apply(this);
    },
    initComponent:function() {
    	this.composeButton = {
    		iconCls: 'compose', 
        	handler: this.composeCallbackHandler
    	}
    	this.refreshButton = {
    		iconCls: 'refresh',
        	handler: this.reloadCallbackHandler
    	}
    	this.items = this.items || [];
    	this.items.unshift(this.refreshButton);
    	this.items.unshift({xtype: 'spacer'});
    	this.items.unshift(this.composeButton);
    	Messenger.ui.SouthToolbar.superclass.initComponent.call(this);
    } 
});

Messenger.ui.MessageField = Ext.extend(Ext.form.Text, {
    id: 'messageField',
    name : 'message',
    placeHolder: 'Deine Message...',
    required: true,
    useClearIcon: true,
    enableKeyEvents: true
});

Messenger.ui.MessageButton = Ext.extend(Ext.Button, {
	text: 'Send',
	ui: 'confirm',
	height: 45
});

Messenger.ui.MessageOverlayPanel = Ext.extend(Ext.Panel, {
    floating: true,
    modal: true,
    centered: false,
    width: 300,
    height: 120,
    scroll: 'vertical',
    layout: {
    	type: 'hbox'
    },
    initComponent:function() {
    	this.messageField = new Messenger.ui.MessageField({
    		listeners: {
    			keyup: function(field, event) {
    				if(event.browserEvent.keyCode == 13){
    					this.onMessageButtonClicked(field, event, this.messageField);
    				}
    	    	},
    	    	scope: this
    		},
    		scope: this
    	});
    	this.messageButton = new Messenger.ui.MessageButton({
    		handler: function(btn, event) {
    			this.onMessageButtonClicked(btn, event, this.messageField);
    		},
    		scope: this
    	});
    	this.fieldSet = new Ext.form.FieldSet({
    		title: 'Nachricht verfassen...',
            layout: {
            	type: 'hbox'
            },
            items: [this.messageField, this.messageButton]
    	});
    	this.items = this.items || [];
    	this.items.unshift(this.fieldSet);
    	Messenger.ui.MessageOverlayPanel.superclass.initComponent.call(this);
    },
    
    onMessageButtonClicked: function(btn, event, messageField) {
    	Ext.Ajax.request({
    		url: '/message',
    		params: 'mode=save&message=' + messageField.getValue(),
    		success: function(response, opts) {
    			messageField.setValue();
    		},
    		failure: function(response, opts) {
    			Ext.Msg.alert('Uuops..', response.message);
    		}
    	});
    	this.hide();
    }
});

/**
 * Application entry point.
 */
Ext.setup({
	tabletStartupScreen: 'resources/img/large-loading.gif',
    phoneStartupScreen: 'resources/img/large-loading.gif',
    icon: 'resources/img/transmit_blue.png',
    glossOnIcon: false,
    onReady: function() {
    	messageStore = new Ext.data.Store({
    		storeId: 'messageStore',
    	    model: 'Message',
    	    sorters: {
                property : 'timestamp',
                direction: 'DESC'
            },
    	    autoLoad: false,
    	    getGroupString: function(record) {
    	    	var date = new Date(record.data.timestamp);
    	    	var month = date.getMonth() + 1;
    	    	var createDate = date.getDate() + '.' + month + '.' + date.getFullYear();
    	    	return createDate;
    	    },
    	    proxy: {
    	        type: 'ajax',
    	        url : '/message?mode=list',
    	        reader: {
    	            type: 'json',
    	            root: 'data'
    	        }
    	    }
    	});

    	var reloadMessages = function(btn, event) {
    		messageStore.load();
        };
    	
        var messageList = new Messenger.ui.MessageList({
        	store: messageStore
        });
        
        var teamHandler = function(btn, event) {
        	if (rootPanel.getActiveItem().id == 'messageList') {
    			rootPanel.setActiveItem(1);
    		} else {
    			rootPanel.setActiveItem(0);
    		}
    	}
        
        var logoutHandler = function(btn, event) {
    		window.location = "/logout";
    	}
        
        var northToolbar = new Messenger.ui.NorthToolbar({
            teamCallbackHandler: teamHandler,
            logoutCallbackHandler: logoutHandler
        });
        
    	var messageField = new Messenger.ui.MessageField();
    	
    	var overlay = new Messenger.ui.MessageOverlayPanel();
    	
    	var showOverlay = function(btn, event) {
            overlay.showBy(btn);
        };
    	
        var southToolbar = new Messenger.ui.SouthToolbar({
        	composeCallbackHandler: showOverlay,
        	reloadCallbackHandler: reloadMessages
        });
        
    	var userList = {
    			style: 'background-color: red; color: withe;',
    			title: 'red',
    			html: 'Nothing houh?'
    	}
    	
        rootPanel = new Messenger.ui.RootPanel({
            items: [messageList, userList],
            dockedItems: [northToolbar, southToolbar]
        });
    	
    	var channelTokenCookie = getCookie('channelToken')
    	
    	if(channelTokenCookie) {
    		console.info("Old channel token found: " + channelTokenCookie);
    		openSocketConnection(channelTokenCookie, messageStore);
    	} else {
    		console.info("No channel token found: request for new token.");
    		Ext.Ajax.request({
        		url : '/token' , 
        		method: 'GET',
        		success: function ( result, request ) { 
        			console.info("New channel token recieved: " + result.responseText);
        			openSocketConnection(result.responseText, messageStore);
        		},
        		failure: function ( result, request) { 
        			Ext.Msg.alert('Uuops..', result.message);
        		} 
        	});
    	}
    }
});

function openSocketConnection(channelToken, messageStore) {
	if (channelToken) {
		var channel = new goog.appengine.Channel(channelToken);
	    var socket = channel.open();
	    socket.onopen = function() {
	    	console.info("Socket opened: " + channelToken);
	    	if(getCookie('channelToken')) {
	    		//nothing to do, still deal with old cookie token.
	    	} else {
	    		setCookie('channelToken', channelToken, 1000*60*120);
	    	}
	    	messageStore.load();
	    };
	    socket.onmessage = function(message) { 
	    	var passedMessage = Ext.decode(message.data);
	    	if (passedMessage.success) {
	    		var passedMessageModels = passedMessage.data;
	    		Ext.each(passedMessageModels, function(messageModel, index) {
	    			messageStore.insert(0, messageModel);
	    		});
	    		console.info("Socket message success: " + passedMessage.message);
	    	} else {
	    		console.error("Socket message failure: " + passedMessage.message); 
	    	}
	    };
	    socket.onerror = function(error) { 
	    	console.error("Socket error: " + error.description + " (" + error.code + ")");
	    	showError(error);
	    };
	    socket.onclose = function() { 
	    	console.info("Socket closed: " + channelToken); 
	    };
	} else {
		console.error("Invalid Channel Token: " + channelToken); 
		Ext.Msg.alert('Uuops..', "Invalid Channel Token: " + channelToken);
	}
}

function showError(error) {
	Ext.Msg.alert('Uuops..', error.description + " (" + error.code + ")", function() {
		if (error.code && (error.code == 500 || error.code == 401)) {
			deleteCookie('channelToken');
			location.reload();
		}
	});
}